package com.xhwl.centiotdata.pushtrigger.device;

import com.alibaba.druid.support.json.JSONUtils;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.xhwl.centiotdata.service.cent.IDeviceCentService;
import com.xhwl.centiotdata.service.cent.IProjectCentService;
import com.xhwl.common.dto.cent.device.DeviceDTO;
import com.xhwl.common.dto.cent.device.iot.*;
import com.xhwl.common.enums.centsecurity.PerimeterStatusEnum;
import com.xhwl.common.enums.device.DeviceOnlineStatusEnum;
import com.xhwl.common.pojo.ResultJson;
import com.xhwl.common.pojo.cent.device.Device;
import com.xhwl.common.pojo.cent.device.DeviceStatusRecord;
import com.xhwl.common.pojo.cent.sdata.Project;
import com.xhwl.common.query.cent.device.DevicePageQuery;
import com.xhwl.common.query.cent.device.DeviceQuery;
import com.xhwl.common.query.cent.sdata.ProjectQuery;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.ResponseEntity;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author zhengss
 * @since 2021/3/31
 * ================== 订阅iotDA接口，接收增删改设备数据，接口经过网关白名单不鉴权 =======================
 * 特别说明：本接口类接收iotDA平台的订阅推送，属性字段命名采用下划线连字符格式以匹配推送内容。
 * 处理设备的新增、删除、设备在离线状态
 */
@Slf4j
@RestController
public class HuaweiIotDeviceController {

    private final int ACTIVE = 1;

    @Autowired
    private IDeviceCentService deviceService;

    @Autowired
    private IProjectCentService projectService;


    /**
     * @param iotDeviceJson
     * {
     * "resource":"device",
     * "notify_data":{
     * 	"body":{
     * 		"app_id":"a5a61063858f4221bd22b67ef4cdbb2e",
     * 		"app_name":"jinmao",
     * 		"product_id":"603f5cdcaaafca02d8602917",
     * 		"product_name":"sgf",
     * 		"gateway_id":"132456",
     * 		"device_id":"132456",
     * 		"device_name":"摄像头1",
     * 		"node_type":"GATEWAY",
     * 		"node_id":"ABC123456789",
     * 		"auth_info":{
     * 			"auth_type":"SECRET",
     * 			"secure_access":false,
     * 			"timeout":0
     * 			},
     * 		"extension_info":{
     * 			"projectId":"SH2201",
     * 			"product_id": 2,
     * 			"supplier_id":3,
     * 			"detail_position": "示例：教学楼-三楼-3号教室-后排墙角",
     * 			{"water_temperature":"25C"},
     * 			},
     * 		"create_time":"20210327T061503Z",
     * 		"status":"INACTIVE"
     * 		}
     * 	},
     * "event":"create",
     * "event_time":"20210327T061503Z"
     * }
     *
     * 敢为接入规范
     * 【node_id = projectId_categoryId_productId_deviceTypeId_第三方设备id】
     * 【device_name = 设备安装详细位置_设备名称】
     */
    @PostMapping("/iot-device/create-device")
    public void createDevice(@RequestBody IotDeviceJson<CreateDeviceBody> iotDeviceJson) {
        log.info("金茂接入数据json：{}", JSONObject.toJSONString(iotDeviceJson));
        log.info(iotDeviceJson.toString());
        if (StringUtils.isEmpty(iotDeviceJson)) {
            log.info("推送的数据为空");
        }
        NotifyData<CreateDeviceBody> notifyData = iotDeviceJson.getNotify_data();
        Integer porjectId;
        Integer categoryId = 0;
        Integer productId;
        Integer deviceTypeId;
        String thirdDeviceId;

        Integer projectId = 1;
        if ("device".equals(iotDeviceJson.getResource()) && "create".equals(iotDeviceJson.getEvent())) {
            CreateDeviceBody iotDeviceBody = notifyData.getBody();
            Device device = new Device();
            String nodeId = iotDeviceBody.getNode_id();
            String[] split = nodeId.split("_");

            String projectCode = split[0];
            projectId = getProjectId(projectCode);
            if (split.length>0) {
                categoryId = Integer.valueOf (split[1]);
                productId = Integer.valueOf (split[2]);
                deviceTypeId = Integer.valueOf (split[3]);
                thirdDeviceId = split[4];
                device.setProjectId(projectId);
                device.setCategoryId(categoryId);
                device.setProductId(productId);
                device.setDeviceTypeId(deviceTypeId);
                device.setThirdDeviceId(thirdDeviceId);
                device.setName(iotDeviceBody.getDevice_name());
                device.setDetailPosition(iotDeviceBody.getDevice_name());
                device.setIotDeviceId(iotDeviceBody.getDevice_id());
                final DeviceOnlineStatusEnum status = DeviceOnlineStatusEnum.getByCode(iotDeviceBody.getStatus());
                //如果状态时已经激活的即，枚举id>-1时，要设置设备激活状态和设备在离线状态
                /**
                 * 未激活：
                 * INACTIVE(0, "INACTIVE", "未激活"),
                 * OFFLINE(0, "OFFLINE", "离线"),
                 *
                 *激活：
                 * ACTIVE(1, "ACTIVE", "激活"),
                 * ONLINE(1, "ONLINE", "在线"),
                 * ABNORMAL(2, "ABNORMAL", "异常");
                 *
                 */
                // status >= 1
                if(status.getId() >= DeviceOnlineStatusEnum.ACTIVE.getId()){
                    // 设备状态：0未激活，1激活
                    device.setDeviceStatus(1);
                    // status >= 0 实际：status >= 1
                    if(status.getId() >=DeviceOnlineStatusEnum.OFFLINE.getId()){
                        // 设备在离线：0离线、1在线、2异常（出现，1-在线、2-异常）
                        device.setOnlineStatus(status);
                    }
                    //否则只需要设置激活、未激活即可
                }else {
                    device.setDeviceStatus(0);
                }
                device.setNodeId(iotDeviceBody.getNode_id());
                device.setAttributeJson(JSON.parseObject(iotDeviceBody.getAuth_info()));
            }else{
                log.error("回调推送的node_id是"+nodeId+"不符合约定规范");
            }
            device.setCreatedAt(iotDeviceBody.getCreate_time());
            device.setUpdatedAt(iotDeviceBody.getCreate_time());
            try {
                ResultJson resultJson = deviceService.batchSave(null, Arrays.asList(device));
                log.info(resultJson.toString());
            } catch (Exception e) {
                log.error("iotDA订阅新增设备，我方新增失败，请查找系统错误原因，报错如下：" + e.getMessage());
            }
        }
    }

    private Integer getProjectId(String projectCode) {
        ProjectQuery projectQuery = new ProjectQuery();
        projectQuery.setCode(projectCode);
        List<Project> projects = projectService.list(projectQuery, null);
        return projects.size()>0 ? projects.get(0).getId() : 1;
    }

    /**
     * @param iotDeviceJson {
     *                      "resource":"device",
     *                      "notify_data":{
     *                      "header":{
     *                      "device_id":"603f5cdcaaafca02d8602917_agfagas",
     *                      "product_id":"603f5cdcaaafca02d8602917",
     *                      "app_id":"a5a61063858f4221bd22b67ef4cdbb2e",
     *                      "gateway_id":"603f5cdcaaafca02d8602917_agfagas",
     *                      "node_id":"agfagas"
     *                      }
     *                      },
     *                      "event":"delete",
     *                      "event_time":"20210401T012015Z"
     *                      }
     */
    @PostMapping("/iot-device/delete-device")
    public void deleteDevice(@RequestBody IotDeviceJson iotDeviceJson) {
        log.info("金茂接入数据json 删除：{}", JSONObject.toJSONString(iotDeviceJson));
        log.info(iotDeviceJson.toString());
        if (StringUtils.isEmpty(iotDeviceJson)) {
        }
        String event = iotDeviceJson.getEvent();
        String resource = iotDeviceJson.getResource();
        NotifyData notify_data = iotDeviceJson.getNotify_data();
        Integer projectId = 1;
        if ("device".equals(resource) && "delete".equals(event)) {
            CommonHeader header = notify_data.getHeader();
            String iotDeviceId = header.getDevice_id();
            String node_id = header.getNode_id();
            String[] split = node_id.split("_");
            String projectCode = split[0];
            projectId = getProjectId(projectCode);
            try {
                DeviceQuery deviceQuery = new DeviceQuery();
                deviceQuery.setProjectId(projectId);
                deviceQuery.setIotDeviceId(iotDeviceId);
                log.info("删除数据：{}", deviceQuery);
                boolean delete = deviceService.deleteByIotIdV2(deviceQuery);
                log.info(delete ? "删除成功" : "删除失败”");
            } catch (Exception e) {
                log.error("iotDA订阅删除设备，我方删除失败，请查找系统错误原因，报错如下：" + e.getMessage());
            }
        }
    }



    /**
     * 接入敢为iotDA设备状态同步
     * {
     * 	"resource":"device.status",
     * 	"notify_data":{
     * 		"device_id":"1_XYJM001_12_100001",  //iotProductId_projectCode_categoryId_thirdDeviceId
     * 		//注意，device_id是iot的productId+nodeId的组合，这里1是productId，1_12_100001是nodeId
     * 	    // nodeId的规范格式是：projectCode_categoryId_productId_deviceTypeId_第三方设备id，
     * 	    "node_id": "XYJM01_14_1_9_4002",
     * 	    // 这里的projectId已经替换为兴海的projectCode，通过projectCode找对应的projectId
     * 		"app_id":"c9c3f09f28434760b4f2a0b6c4f116a2",
     * 		"status":"ONLINE",
     * 		"timestamp":"20211205T085357Z"
     *        },
     * 	"event":"update"
     * }
     * @param iotDeviceJson
     */
    @PostMapping("/iot-device/status-change")
    public void changeStatus(@RequestBody IotDeviceJson<IotDeviceStatus> iotDeviceJson) throws ParseException {
        log.info("金茂接入数据json 状态：{}", JSONObject.toJSONString(iotDeviceJson));
        if (StringUtils.isEmpty(iotDeviceJson)) {
            return;
        }
        NotifyData<IotDeviceStatus> notifyData = iotDeviceJson.getNotify_data();
        IotDeviceStatus body = notifyData.getBody();

        String status = body.getStatus();
        String last_online_time = body.getLast_online_time();

        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd'T'HHmmss'Z'");
        //设置时区为UTC时区， 表示format的时区是UTC， parse时会根据本地时区进行转换
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
        //由于Date没有时区的概念， parse时转换的UTC时间会转换成本地时间， 例如：转换成北京时间时， 时间+8 为2019-07-11 00:00:00
        Date lastOnlineTime = sdf.parse(last_online_time);

        Device device = new Device();
        device.setUpdatedAt(lastOnlineTime);
        // 激活 同时更新设备状态 ONLINE
        device.setOnlineStatus(DeviceOnlineStatusEnum.getByCode(status));
        device.setDeviceStatus(ACTIVE);

        CommonHeader header = notifyData.getHeader();
        String nodeId = header.getNode_id();
        String iotDeviceId = header.getDevice_id();
        String  projectCode = nodeId.split("_")[0];
        Integer categoryId = Integer.valueOf(nodeId.split("_")[1]);
        Integer productId = Integer.valueOf(nodeId.split("_")[2]);
        Integer deviceTypeId = Integer.valueOf(nodeId.split("_")[3]);

        Integer projectId = 1; //默认projectId为1
        projectId = getProjectId(projectCode);
        device.setProjectId(projectId);
        device.setIotDeviceId(iotDeviceId);
        //device.setCategoryId(categoryId);
        //device.setProductId(productId);
        //device.setDeviceTypeId(deviceTypeId);
        //1根据projectId和iotDeviceId更新设备状态
        try {
            log.info("金茂接入数据json状态同步到设备中台：{}", JSONObject.toJSONString(device));
            deviceService.asyncUpdateOnlineStatus(Arrays.asList(device));
        } catch (Exception e) {
            log.error("iotDA订阅更新设备，我方更新失败，请查找系统错误原因，报错如下：" + e.getMessage());
        }
        DeviceQuery deviceQuery = new DeviceQuery();
        deviceQuery.setProjectId(projectId);
        deviceQuery.setIotDeviceId(iotDeviceId);
        List<DeviceDTO> list = deviceService.list(null,deviceQuery);
        DeviceDTO deviceDTO = new DeviceDTO();
        if (!CollectionUtils.isEmpty(list)){
            deviceDTO = list.get(0);
        }
        //2记录设备状态变更到设备状态记录表中
        DeviceStatusRecord deviceStatusRecord = new DeviceStatusRecord();
        deviceStatusRecord.setDeviceId(deviceDTO.getId());
        deviceStatusRecord.setProjectId(projectId);
        deviceStatusRecord.setIotDeviceId(iotDeviceId);
        deviceStatusRecord.setStatus(DeviceOnlineStatusEnum.getByCode(status));
        try {
            boolean save = deviceService.saveRecord(deviceStatusRecord);
            log.info(save ? "新增设备状态记录成功" : "iotDA订阅新增设备状态记录，我方新增失败”");
        } catch (Exception e) {
            log.error("iotDA订阅新增设备状态，新增失败，请查找系统错误原因，报错如下：" + e.getMessage());
        }
    }

    /**
     * @Description:    示例：接收环境设备属性上报
     * @Author:         zhengss
     * @CreateDate:     2021/6/18 16:12
     * @version:        1.0
     *{
     * 	"resource":"device.property",
     * 	"notify_data":{
     * 		"header":{
     * 			"device_id":"61987f96d50ad802887831e5_1638689931322",
     * 			"product_id":"61987f96d50ad802887831e5",
     * 			"app_id":"c9c3f09f28434760b4f2a0b6c4f116a2",
     * 			"gateway_id":"61987f96d50ad802887831e5_1638689931322",
     * 			"node_id":"1638689931322"
     * 		},
     * 		"body":{
     * 			"services":[
     * 				{
     * 				"service_id":"AirQuality",
     * 					"properties":{
     * 					"PM25":"13-PM25",
     * 					"CO2":"11-CO2",
     * 					"PM10":"12-PM10"
     * 					},
     * 				"event_time":"20211205T074744Z"
     * 				}
     * 			]
     * 		}
     * 	},
     * 	"event":"report",
     * 	"event_time":"20211205T074744Z"
     * }
     * -----
     */
    @PostMapping("/iot-device/service-content")
    public void deviceServiceContentTest(@RequestBody IotDeviceJson<DeviceServiceBody<Object>> iotDeviceJson) {
//        log.info("iotDeviceJson:{}",iotDeviceJson);
        Object properties = iotDeviceJson.getNotify_data().getBody().getServices().get(0).getProperties();
        DeviceService<Object> deviceService = iotDeviceJson.getNotify_data().getBody().getServices().get(0);
        Date eventDate = deviceService.getEvent_time();

        String jsonString = JSONUtils.toJSONString(properties);

        CommonHeader header = iotDeviceJson.getNotify_data().getHeader();
        String node_id = header.getNode_id();
        String[] split = node_id.split("_");
        Integer deviceTypeId = Integer.valueOf(split[3]);
        //iot设备id，格式（产品id_项目id_系统大类id_子系统id_第三方设备id）
        String iotDeviceId = header.getDevice_id();
        Integer projectId = 1;

        //...后续业务...
        switch (deviceTypeId){
            case 1:
//        1	门禁闸机
                break;
            case 2:
//        2	摄像头
                break;
            case 3:
//        3	车场闸机
                break;
            case 4:
//        4	巡更设备
                break;
            case 5:
//        5	电子围栏设备
                IotPerimeterDevice iotPerimeterDevice = JSONObject.parseObject(JSONObject.toJSONString(properties),IotPerimeterDevice.class);
                log.info("iotPerimeterDevice:{}",iotPerimeterDevice.toString());
                if(!StringUtils.isEmpty(iotPerimeterDevice.getDeployStatus())){
                    String deployStatus = iotPerimeterDevice.getDeployStatus();
                    DevicePageQuery deviceQuery = new DevicePageQuery();
                    deviceQuery.setIotDeviceId(iotDeviceId);
                    List<DeviceDTO> deviceDTOList = this.deviceService.listDevice(null, deviceQuery);
                    if(!deviceDTOList.isEmpty()){
                        DeviceDTO deviceDTO = deviceDTOList.get(0);
                        JSONObject attributeJson = deviceDTO.getAttributeJson();
                        if(attributeJson == null){
                            attributeJson = new JSONObject();
                        }
                        //设防、旁路、 撤防
                        attributeJson.put("protection",PerimeterStatusEnum.getPerimeterStatusEnum(deployStatus).getValue());
                        deviceDTO.setAttributeJson(attributeJson);
                        this.deviceService.batchUpdate(null,Collections.singletonList(deviceDTO));
                    }
                }
                break;
            case 6:
//        6	一键告警箱
                break;
            case 7:
//        7	空气监测传感器
                IotAirQuality iotAirQuality = JSONObject.parseObject(JSONObject.toJSONString(properties),IotAirQuality.class);
                break;
            case 8:
//        8	温湿度传感器
                break;
            case 9:
//        9	烟感
                break;
            case 10:
//        10	水表
                break;
            case 11:
//        11	电表
                break;
            case 12:
//        12	电梯
                IotElevatorDevice iotElevatorDevice = JSONObject.parseObject(JSONObject.toJSONString(properties),IotElevatorDevice.class);
                break;

            case 13:
//        13	照明
                break;

            case 14:
//        14	排风机组
                break;
            case 15:
//        15	水泵
                IotWaterPumpDevice iotWaterPumpDevice = JSONObject.parseObject(JSONObject.toJSONString(properties),IotWaterPumpDevice.class);
                break;
            case 16:
//        16	空调
                break;
            case 17:
//        17	新风机组
                break;
            case 18:
//        18	云对讲
                break;
            case 19:
//        19	噪音监测设备
                break;
            case 20:
//        20	风力监测设备
                break;
            case 21:
//        21	燃气表
                break;
            case 22:
//        22	环境设备
                break;
            case 23:
//        23	对讲室外云屏
                break;
            case 24:
//        24	对讲室内云屏
                break;
            case 25:
//        25	BA-高速风机
                break;
            case 26:
//        26	BA-单速风机
                break;
            case 27:
//        27	BA-冷热泵空调
                break;
            default:
        }

    }

    /**
     * 测试接口
     * @param object
     * @param headers
     * @param request
     * @return
     */
    @RequestMapping("/iot-device/iot-msg")
    public Object receiveIotPush(@RequestBody Object object, @RequestHeader HttpHeaders headers, HttpServletRequest request){

        log.error("=============service-content===============");
        String jsonString = JSONUtils.toJSONString(object);
        log.info(jsonString);
        log.error("============================");
        //headers.entrySet().forEach(item->{
        //    System.out.println(item.getKey()+":"+item.getValue());
        //});
        //System.out.println(request.getHeaderNames());
        //log.error("============================");
        //String remoteAddr = "";
        //System.out.println();
        //if (request != null) {
        //    remoteAddr = request.getHeader("X-FORWARDED-FOR");
        //    if (remoteAddr == null || "".equals(remoteAddr)) {
        //        remoteAddr = request.getRemoteAddr();
        //        System.out.println("+++++++++++"+remoteAddr+"+++++++++++++");
        //    }
        //}
        return ResponseEntity.ok(object);
    }




}
